<template>
  <div>
    <div class="player">
      <div class="player-main">
        <div class="player-main-left" @click="toMusicMsg(currentMusic.id)">
          <img v-lazy="currentMusic.nowImgUrl" />
        </div>
        <div class="player-main-main" @click="toMusicMsg(currentMusic.id)">
          <div>
            <div class="musicname">{{ currentMusic.nowName }}</div>
            <div class="artistsname">
              <span
                v-for="(item, index) in currentMusic.nowArtists"
                :key="item.id || item.name"
                >{{ item.name
                }}<span v-if="index < currentMusic.nowArtists.length - 1"
                  >/</span
                ></span
              >
            </div>
          </div>
        </div>
        <div class="player-main-right">
          <span class="icon-list" @click="openBottomSheet"></span>
          <span class="icon-next" @click="nextAction().then()"></span>
          <span class="icon-pause" @click="play(false)" v-if="isPlaying"></span>
          <span class="icon-play" @click="play(true)" v-else></span>
        </div>
      </div>
      <mu-linear-progress
        :value="currentTimeInfo.value1"
        mode="determinate"
      ></mu-linear-progress>
    </div>
    <mu-bottom-sheet
      :open="bottomSheetShow"
      @close="closeBottomSheet"
      :sheetClass="{ maxHeight: bottomSheetShow }"
    >
      <mu-list :value="currentMusic.id" @itemClick="closeBottomSheet">
        <mu-sub-header> 播放列表({{ musicUrlList.length }}) </mu-sub-header>
        <mu-list-item
          v-for="(item, index) of musicUrlList"
          :key="item.id"
          :title="item.name + ' - ' + item.artists[0].name"
          :value="item.id"
          class="demo-list"
          @click="changeMusic(index, item.id).then()"
        >
          <mu-icon value="ic_close" slot="right" />
        </mu-list-item>
      </mu-list>
    </mu-bottom-sheet>
    <audio
      :src="currentMusic.nowMusicUrl"
      ref="audio"
      @ended="toNext"
      @loadedmetadata="initFullTime"
      @timeupdate="updateCurrentTime"
    ></audio>
  </div>
</template>

<script lang="ts">
import { CurrentMusic } from "@/model/current-music.model";
import { CommonIdType, PlayModel } from "@/model/id-or-enum.model";
import { MusicInfo } from "@/model/music-info.model";
import { CurrentTimeInfo, FullTimeInfo } from "@/model/playing-info.model";
import { Component, Ref, Vue, Watch } from "vue-property-decorator";
import { namespace } from "vuex-class";
import Router, { Route } from "vue-router";
import { APIType } from "@/api/index";
import { AudioAction } from "@/utils/event";
import { Subscription } from "rxjs";
const AppModule = namespace("app");
@Component({
  components: {},
})
export default class MusicControllerComponent extends Vue {
  // 是否显示播放列表
  public bottomSheetShow: boolean = false;
  $api: APIType;

  // 播放列表
  @AppModule.State("musicUrlList")
  public musicUrlList: MusicInfo[];
  // 是否正在播放（没被暂停）
  @AppModule.State("isPlaying")
  public isPlaying: boolean;
  // 播放模式： 单曲、循环、随机
  @AppModule.State("playModel")
  public playModel: PlayModel;
  // 当前歌曲信息
  @AppModule.State("nowMusic")
  public currentMusic: CurrentMusic;
  // 当前歌曲总时长
  @AppModule.State("full")
  public fullTimeInfo: FullTimeInfo;
  // 当前播放进度
  @AppModule.State("current")
  public currentTimeInfo: CurrentTimeInfo;

  // 设置当前歌曲总时长
  @AppModule.Mutation("setFullTimeInfo")
  public setFullTimeInfo: (info: FullTimeInfo) => void;
  // 设置当前歌曲进度
  @AppModule.Mutation("setCurrentTimeInfo")
  public setCurrentTimeInfo: (info: CurrentTimeInfo) => void;
  // 设置播放状态
  @AppModule.Mutation("setIsPlaying")
  public setIsPlaying: (value: boolean) => void;
  // 设置当前播放歌曲
  @AppModule.Mutation("setCurrentMusicInfo")
  public setCurrentMusicInfo: (info: CurrentMusic) => void;
  // 设置播放工具栏的显示隐藏
  @AppModule.Mutation("setShowController")
  public setShowController: (value: boolean) => void;

  // 选中ref="audio"的标签
  @Ref("audio") readonly audio!: HTMLAudioElement;

  $router: Router;
  $route: Route;

  private audioSubscription: Subscription;

  public mounted() {
    this.destroyListener();
    this.play(false);
    this.audioSubscription = AudioAction.subscribe((param) => {
      if (param.isPlaying != null) {
        this.play(param.isPlaying);
      }
      if (param.currentTimeInfo != null) {
        this.audio.currentTime = param.currentTimeInfo.currentTime;
        this.setCurrentTimeInfo(param.currentTimeInfo);
      }
    });
  }

  private destroyListener() {
    if (this.audioSubscription) {
      this.audioSubscription.unsubscribe();
      this.audioSubscription = null;
    }
  }

  public beforeDestroy() {
    this.destroyListener();
  }

  // 播放下一首
  toNext() {
    if (
      this.playModel === PlayModel.Sequence ||
      this.playModel === PlayModel.Random
    ) {
      // console.log('列表循环模式播放或随机播放')
      this.nextAction(); // 下一首
    } else if (this.playModel === PlayModel.Single) {
      // console.log('单曲模式播放')
      this.audio.currentTime = 0;
      this.audio.play();
    }
  }
  // 初始化总时长信息
  initFullTime() {
    const fullTime: number = this.audio.duration;
    // padStart为了使类似时间1:9，显示为01:09
    const fullMin: string = Math.floor(fullTime / 60)
      .toString()
      .padStart(2, "0");
    const fullSec: string = Math.floor(fullTime % 60)
      .toString()
      .padStart(2, "0");
    const fullTimeInfo: FullTimeInfo = { fullTime, fullMin, fullSec };
    this.setFullTimeInfo(fullTimeInfo);
  }
  // 更新进度信息
  updateCurrentTime() {
    const currentTime: number = this.audio.currentTime;
    const value1 = (currentTime / this.fullTimeInfo.fullTime) * 100;
    const currentMin = Math.floor(currentTime / 60)
      .toString()
      .padStart(2, "0");
    const currentSec = Math.floor(currentTime % 60)
      .toString()
      .padStart(2, "0");
    const currentTimeInfo: CurrentTimeInfo = {
      currentTime,
      currentMin,
      currentSec,
      value1,
    };
    this.setCurrentTimeInfo(currentTimeInfo);
  }
  // 播放/暂停
  play(isPlaying: boolean) {
    if (isPlaying) {
      this.audio.play();
    } else {
      this.audio.pause();
    }
    this.setIsPlaying(isPlaying);
  }
  // 播放下一首执行的动作
  async nextAction() {
    let index;
    // 获得下一首歌曲的id
    let id;
    if (
      this.playModel === PlayModel.Sequence ||
      this.playModel === PlayModel.Single
    ) {
      // 如果是歌曲的最后一首，则ind为0，以便下次取到的是第一首
      index =
        this.currentMusic.index === this.musicUrlList.length - 1
          ? 0
          : this.currentMusic.index + 1;
      id = this.musicUrlList[index].id;
    } else {
      index = Math.floor(Math.random() * this.musicUrlList.length);
      id = this.musicUrlList[index].id;
    }
    // 由于获取的歌单，没有歌曲的url，需要先ajax请求url，再发送
    const musics = await this.$api.getMusicUrl(id);
    const music = musics?.[0];
    // 下一首歌曲的url
    const url = music.url;
    const { name, artists, imgUrl } = this.musicUrlList[index];
    const currentMusic: CurrentMusic = {
      id,
      index,
      nowMusicUrl: url,
      nowName: name,
      nowArtists: artists,
      nowImgUrl: imgUrl,
    };
    this.setIsPlaying(true);
    this.setCurrentMusicInfo(currentMusic);
  }
  // 跳转到歌曲详情
  toMusicMsg(id: CommonIdType) {
    this.setShowController(false);
    this.$router.push({ path: `/music/${id}` }).catch((err) => err);
  }
  // 关闭歌曲列表
  closeBottomSheet() {
    this.bottomSheetShow = false;
  }
  // 开启歌曲列表
  openBottomSheet() {
    this.bottomSheetShow = true;
  }
  async changeMusic(index: number, id: CommonIdType) {
    // console.log(index);
    const musics = await this.$api.getMusicUrl(id);
    const music = musics?.[0];
    // 下一首歌曲的url
    const url = music.url;
    const { name, artists, imgUrl } = this.musicUrlList[index];
    const currentMusic: CurrentMusic = {
      id,
      index,
      nowMusicUrl: url,
      nowName: name,
      nowArtists: artists,
      nowImgUrl: imgUrl,
    };
    this.setIsPlaying(true);
    this.setCurrentMusicInfo(currentMusic);
  }
}
</script>

<style lang="scss">
@import "../assets/scss/icon.scss";
.player-main {
  height: 0.8rem;
  border-top: 1px solid #eff2f7;
  display: flex;
  .player-main-left {
    padding: 0.1rem;
    > img {
      width: 0.6rem;
      height: 0.6rem;
    }
  }
  .player-main-main {
    flex: 1;
    display: flex;
    align-items: center;
    .musicname {
      font-weight: 500;
      font-size: 0.2rem;
    }
    .artistsname {
      font-size: 0.15rem;
      color: #99a9bf;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
  }
  .player-main-right {
    display: flex;
    justify-content: center;
    align-items: center;
    > span {
      margin-right: 0.2rem;
      font-size: 0.4rem;
      color: #df2d2d;
    }
  }
}
.demo-list {
  border-bottom: 0.1px solid #999;
}
.maxHeight {
  max-height: 5rem;
  overflow-y: scroll;
}
</style>
